package basic.bao;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.math.BigDecimal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

import basic.a6.Util;

public class BaseDao<T> {
	private Class<T> classt;
	private String tableName;
	private Field[] field;

	@SuppressWarnings("unchecked")
	public BaseDao() {
		ParameterizedType tp = (ParameterizedType) this.getClass().getGenericSuperclass();
		classt = (Class<T>) tp.getActualTypeArguments()[0];
		tableName = classt.getSimpleName();
		field = classt.getDeclaredFields();
	}

	public void insert(T t) {
		StringBuffer sq = new StringBuffer("insert into ").append(tableName).append("(");// 利用buffer连接
		try {
			int n = 0;
			for (int i = 0; i < field.length; i++) {
				field[i].setAccessible(true); // 私有成员设为可访问
				Object va = field[i].get(t); // 获取字段t
				if (va != null) {// 如果字段不为空
					sq.append(field[i].getName()).append(",");// 在这个字段名的后面追加一个逗号
					n++;
				}
			}
			Object[] val = new Object[n];// 创建一个数组来存储n值
			sq.replace(sq.length() - 1, sq.length(), ")");// 根据sql语句的长度缩减逗号
			sq.append(" values(");// 追加
			int j = 0;
			for (int i = 0; i < field.length; i++) {
				field[i].setAccessible(true);
				Object va = field[i].get(t);
				if (va != null) {
					sq.append("?,"); // =====>追加一个问号和逗号
					val[j++] = va; // 把va字段加到val数组的j++号元素上
				}
			}
			sq.replace(sq.length() - 1, sq.length(), ")");// 追加 并上缩减
			// System.out.println(sq);
			Connection con = Util.getconn();
			PreparedStatement pstm = con.prepareStatement(sq.toString());// buffer用tostring
			for (int i = 0; i < n; i++) {
				pstm.setObject(i + 1, val[i]); // 插入值i+1号对应val【i】的值
			}
			pstm.executeUpdate();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public void delete(T t) {
		StringBuffer sql = new StringBuffer("delete from ").append(tableName).append(" where ");
		field[0].setAccessible(true);
		try {
			Object ob = field[0].getName();// ====>得到输入的字段名
			Object oa = field[0].get(t); // =====>得到输入的字段名的具体删除内容
			sql.append(ob).append("=").append(oa);
			// System.out.println(sql);======》拼接完成
			Connection con = Util.getconn();// ====》加载
			PreparedStatement pstm = con.prepareStatement(sql.toString());// ======》连接数据库并执行sql语句
			pstm.executeQuery();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public List<T> findAll() {
		String sql = "select * from " + tableName;
		return findBySql(sql);
	}

	public T findone(Object id){//直接查询一个只能用主键,select*from table_name where column=?==>问号没有具体的，用preparedstatement传一个参数过来就行
		StringBuffer sql = new StringBuffer("select * from ").append(tableName).append(" where ").append(field[0].getName())
				.append(" =?");
		T o = null;
		try {
			o = classt.newInstance();
			Connection con = Util.getconn();
			PreparedStatement psta = con.prepareStatement(sql.toString());   //相比于statement直接传的是参数
			psta.setObject(1,id);                                              //（列索引，列下的具体参数）
			ResultSet rs= psta.executeQuery();
			rs.next();                                                   //next代表下一行列，只有一列不用写循环
			for (int i = 0; i < field.length; i++) {                    //循环读取符合条件的那一行的所有字段
				field[i].setAccessible(true);               
				Object fv = rs.getObject(i+1);
				if (fv instanceof BigDecimal) {
					BigDecimal bd = (BigDecimal) fv;
					switch (field[i].getType().getSimpleName()) {
					case "int":case "Integer":
						fv = bd.intValue();
						break;
					case "double":case "Double":
						fv = bd.doubleValue();
						break;
					}
				}
				field[i].set(o, fv);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return o;
	}

	public void update(T t, Object o) {         //更新任意字段下的符合条件的一个数据
		StringBuffer sql = new StringBuffer("update ").append(tableName).append(" set ");
		try {
			for (int i = 0; i < field.length; i++) {
				field[i].setAccessible(true);
				Object ob = field[i].get(t);
				if (ob != null) {
					sql.append(field[i].getName()).append(" = ").append(o).append(" where ");
				}
			}
			for (int i = 0; i < field.length; i++) {
				field[i].setAccessible(true);
				Object oa = field[i].get(t);
				if (oa != null) {
					sql.append(field[i].getName()).append(" = ").append(oa);
				}
			}
			// System.out.println(sql);
			Connection con = Util.getconn();
			PreparedStatement pstm = con.prepareStatement(sql.toString());
			pstm.executeQuery();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public List<T> findBySql(String sql){
		List<T> list=new ArrayList<>();
		Connection con = Util.getconn();
		try {
			Statement stm = con.createStatement();
			ResultSet rs = stm.executeQuery(sql);
			while (rs.next()) {
				T t = classt.newInstance();
				for (int i = 0; i < field.length; i++) {
					field[i].setAccessible(true); // 私有成员变为可访问
					Object fv = rs.getObject(i + 1);
					if (fv instanceof BigDecimal) {
						BigDecimal bd = (BigDecimal) fv;
						switch (field[i].getType().getSimpleName()) {
						case "int":case "Integer":
							fv = bd.intValue();
							break;
						case "double":case "Double":
							fv = bd.doubleValue();
							break;
						}
					}
					field[i].set(t, fv);
				}
				list.add(t);
				// Util.close(rs);
				// Util.close(stm);
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return list;
	}
}
